Next | Prev | Top | Contents | Index
Appendix A: Code Example for Index Texture Extension
#include <windows.h>
#include <math.h>
#include <GL/gl.h>
#if !defined(M_PI)
#define M_PI 3.14159265F
#endif
char *className = "OpenGL";
char *windowName = "Color Index Texture";
int winX, winY;
int winWidth, winHeight;
HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;
void (*idleFunc)(HDC hDC);
BOOL textureReplace = FALSE;
/* struct used to manage color ramps */
struct colorIndexState {
GLfloat amb[3]; /* ambient color / bottom of ramp */
GLfloat diff[3]; /* diffuse color / middle of ramp */
GLfloat spec[3]; /* specular color / top of ramp */
GLfloat ratio; /* ratio of diffuse to specular in ramp */
GLint indexes[3]; /* where ramp was placed in palette */
};
#define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))
struct colorIndexState colors[] = {
{
{ 0.0F, 0.0F, 0.0F },
{ 0.1F, 0.6F, 0.3F },
{ 1.0F, 1.0F, 1.0F },
0.75F, { 0, 0, 0 },
},
{
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.2F, 0.5F },
{ 1.0F, 1.0F, 1.0F },
0.75F, { 0, 0, 0 },
},
{
{ 0.0F, 0.05F, 0.05F },
{ 0.6F, 0.0F, 0.8F },
{ 1.0F, 1.0F, 1.0F },
0.75F, { 0, 0, 0 },
},
};
void
drawTorus(void)
{
int numMajor = 32;
int numMinor = 24;
float majorRadius = 0.6F;
float minorRadius = 0.2F;
double majorStep = 2.0F*M_PI / numMajor;
double minorStep = 2.0F*M_PI / numMinor;
int i, j;
for (i=0; i<numMajor; ++i) {
double a0 = i * majorStep;
double a1 = a0 + majorStep;
GLfloat x0 = (GLfloat) cos(a0);
GLfloat y0 = (GLfloat) sin(a0);
GLfloat x1 = (GLfloat) cos(a1);
GLfloat y1 = (GLfloat) sin(a1);
glBegin(GL_TRIANGLE_STRIP);
for (j=0; j<=numMinor; ++j) {
double b = j * minorStep;
GLfloat c = (GLfloat) cos(b);
GLfloat r = minorRadius * c + majorRadius;
GLfloat z = minorRadius * (GLfloat) sin(b);
glNormal3f(x0*c, y0*c, z/minorRadius);
glTexCoord2f(i/(GLfloat) numMajor, j/(GLfloat) numMinor);
glVertex3f(x0*r, y0*r, z);
glNormal3f(x1*c, y1*c, z/minorRadius);
glTexCoord2f((i+1)/(GLfloat)numMajor, j/(GLfloat)numMinor);
glVertex3f(x1*r, y1*r, z);
}
glEnd();
}
}
void setCheckTexture(void)
{
int texWidth = 64;
int texHeight = 64;
GLubyte *texPixels, *p;
int texSize;
int i, j;
texSize = texWidth*texHeight*1*sizeof(GLubyte);
if (textureReplace) {
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
} else {
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
texPixels = (GLubyte *) malloc(texSize);
if (texPixels == NULL) {
return;
}
p = texPixels;
for (i=0; i<texHeight; ++i) {
for (j=0; j<texWidth; ++j) {
int rampIndex = textureReplace ? 1 : 0;
if ((i ^ j) & 4) {
*p = colors[0].indexes[rampIndex] & 0xff;
} else {
*p = colors[1].indexes[rampIndex] & 0xff;
}
p += 1;
}
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
texWidth, texHeight, 0,
GL_COLOR_INDEX, GL_UNSIGNED_BYTE, texPixels);
free(texPixels);
}
/*****************************************************************/
void
setProjection(void)
{
GLfloat aspect = (GLfloat) winWidth / (GLfloat) winHeight;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.5F*aspect, 0.5F*aspect, -0.5F, 0.5F, 1.0F, 3.0F);
glMatrixMode(GL_MODELVIEW);
}
void
setMaterial(void)
{
GLfloat matDiff[4] = { 0.65F, 0.05F, 0.20F, 0.60F };
GLfloat matSpec[4] = { 0.50F, 0.50F, 0.50F, 1.00F };
GLfloat matShine = 20.00F;
GLint indexes[3];
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
indexes[0] = 0;
indexes[1] = colors[0].indexes[1] - colors[0].indexes[0];
indexes[2] = colors[0].indexes[2] - colors[0].indexes[0];
glMaterialiv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, indexes);
}
void
init(HDC hDC)
{
GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F };
glClearColor(colors[2].diff[0], colors[2].diff[1],
colors[2].diff[2], 1.0F);
glClearIndex((GLfloat) colors[2].indexes[1]);
setProjection();
glTranslatef(0.0F, 0.0F, -2.0F);
setMaterial();
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
setCheckTexture();
glEnable(GL_TEXTURE_2D);
}
void resize(HDC hDC)
{
setProjection();
glViewport(0, 0, winWidth, winHeight);
}
void doRedraw(HDC hDC)
{
static GLfloat x, y, z;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(x, 1.0F, 0.0F, 0.0F);
glRotatef(y, 0.0F, 1.0F, 0.0F);
glRotatef(z, 0.0F, 0.0F, 1.0F);
drawTorus();
glPopMatrix();
SwapBuffers(hDC);
x += 5.0F;
if (x > 360.0F) x -= 360.0F;
y += 7.0F;
if (y > 360.0F) y -= 360.0F;
z += 9.0F;
if (z > 360.0F) z -= 360.0F;
}
void redraw(HDC hDC)
{
}
/*****************************************************************/
void setupPalette(HDC hDC)
{
PIXELFORMATDESCRIPTOR pfd;
LOGPALETTE* pPal;
int pixelFormat = GetPixelFormat(hDC);
int paletteSize;
DescribePixelFormat(hDC, pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if (!(pfd.dwFlags & PFD_NEED_PALETTE ||
pfd.iPixelType == PFD_TYPE_COLORINDEX))
{
return;
}
paletteSize = 1 << pfd.cColorBits;
pPal = (LOGPALETTE*)
malloc(sizeof(LOGPALETTE) + paletteSize *
sizeof(PALETTEENTRY));
pPal->palVersion = 0x300;
pPal->palNumEntries = paletteSize;
if (pfd.iPixelType == PFD_TYPE_RGBA) {
/*
** Fill palette with an RGB color ramp
*/
int redMask = (1 << pfd.cRedBits) - 1;
int greenMask = (1 << pfd.cGreenBits) - 1;
int blueMask = (1 << pfd.cBlueBits) - 1;
int i;
for (i=0; i<paletteSize; ++i) {
pPal->palPalEntry[i].peRed =
(((i >> pfd.cRedShift) & redMask) * 255) / redMask;
pPal->palPalEntry[i].peGreen =
(((i >> pfd.cGreenShift) & greenMask) * 255)/
greenMask;
pPal->palPalEntry[i].peBlue =
(((i >> pfd.cBlueShift) & blueMask) * 255)/
blueMask;
pPal->palPalEntry[i].peFlags = 0;
}
} else {
/*
** Fill palette with Color Index color ramps.
*/
int numRamps = NUM_COLORS;
int rampSize = (paletteSize - 20) / numRamps;
int extra = (paletteSize - 20) - (numRamps * rampSize);
int i, r;
/*
** Setup the logical palette so that it can be realized as
** an identity palette
*/
/* start with a copy of the current system palette */
GetSystemPaletteEntries(hDC, 0, paletteSize,
&pPal->palPalEntry[0]);
/* fill in non-static entries with desired colors */
for (r=0; r<numRamps; ++r) {
int rampBase = r * rampSize + 10;
PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
int diffSize = (int) (rampSize * colors[r].ratio);
int specSize = rampSize - diffSize;
for (i=0; i<rampSize; ++i) {
GLfloat *c0, *c1;
GLint a;
if (i < diffSize) {
c0 = colors[r].amb;
c1 = colors[r].diff;
a = (i * 255) / (diffSize - 1);
} else {
c0 = colors[r].diff;
c1 = colors[r].spec;
a = ((i - diffSize) * 255) / (specSize - 1);
}
pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) +
255 * c0[0]);
pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) +
255 * c0[1]);
pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) +
255 * c0[2]);
pe[i].peFlags = PC_NOCOLLAPSE;
}
colors[r].indexes[0] = rampBase;
colors[r].indexes[1] = rampBase + (diffSize-1);
colors[r].indexes[2] = rampBase + (rampSize-1);
}
/* initialize any remaining non-static entries */
for (i=0; i<extra; ++i) {
int index = numRamps*rampSize+10+i;
PALETTEENTRY *pe = &pPal->palPalEntry[index];
pe->peRed = (BYTE) 0;
pe->peGreen = (BYTE) 0;
pe->peBlue = (BYTE) 0;
pe->peFlags = PC_NOCOLLAPSE;
}
}
hPalette = CreatePalette(pPal);
free(pPal);
if (hPalette) {
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
}
}
void setupDC(HDC hDC)
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
1, /* version num */
PFD_DRAW_TO_WINDOW | /* support window */
PFD_SUPPORT_OPENGL | /* support OpenGL */
PFD_DOUBLEBUFFER, /* support double-buffering */
PFD_TYPE_COLORINDEX, /* color index mode */
8, /* 8-bit color depth */
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
0, /* no alpha buffer */
0, /* alpha bits (ignored) */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits (ignored) */
16, /* depth buffer */
0, /* no stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0, /* no layer, visible, damage masks */
};
int SelectedPixelFormat;
BOOL retVal;
SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
if (SelectedPixelFormat == 0) {
(void) MessageBox(WindowFromDC(hDC),
"Failed to find acceptable pixel format.",
"OpenGL application error",
MB_ICONERROR | MB_OK);
exit(1);
}
retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
if (retVal != TRUE) {
(void) MessageBox(WindowFromDC(hDC),
"Failed to set pixel format.",
"OpenGL application error",
MB_ICONERROR | MB_OK);
exit(1);
}
}
LRESULT APIENTRY
WndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message) {
case WM_CREATE:
hDC = GetDC(hWnd);
setupDC(hDC);
setupPalette(hDC);
hGLRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hGLRC);
init(hDC);
idleFunc = doRedraw;
return 0;
case WM_DESTROY:
idleFunc = NULL;
if (hGLRC) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hGLRC);
}
ReleaseDC(hWnd, hDC);
PostQuitMessage(0);
return 0;
case WM_SIZE:
if (hGLRC) {
winWidth = (int) LOWORD(lParam);
winHeight = (int) HIWORD(lParam);
resize(hDC);
return 0;
}
case WM_PALETTECHANGED:
if (hPalette != NULL && (HWND) wParam != hWnd) {
UnrealizeObject(hPalette);
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
redraw(hDC);
return 0;
}
break;
case WM_QUERYNEWPALETTE:
if (hPalette != NULL) {
UnrealizeObject(hPalette);
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
redraw(hDC);
return TRUE;
}
break;
case WM_PAINT:
if (hGLRC) {
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
redraw(hDC);
EndPaint(hWnd, &ps);
return 0;
}
break;
case WM_CHAR:
switch ((int)wParam) {
case VK_ESCAPE:
DestroyWindow(hWnd);
return 0;
default:
break;
}
break;
default:
break;
}
/* Deal with any unprocessed messages */
return DefWindowProc(hWnd, message, wParam, lParam);
}
int APIENTRY
WinMain(
HINSTANCE hCurrentInst,
HINSTANCE hPreviousInst,
LPSTR lpszCmdLine,
int nCmdShow)
{
WNDCLASS wndClass;
HWND hWnd;
MSG msg;
/* Define and register a window class */
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hCurrentInst;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = className;
RegisterClass(&wndClass);
/* Figure out a default size for the window */
winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
/* Create a window of the previously defined class */
hWnd = CreateWindow(
className, /* Window class's name */
windowName, /* Title bar text */
WS_OVERLAPPEDWINDOW | /* The window's style */
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
winX, winY, /* Position */
winWidth, winHeight, /* Size */
NULL, /* Parent window's handle */
NULL, /* Menu handle */
hCurrentInst, /* Instance handle */
NULL); /* No additional data */
/* Map the window to the screen */
ShowWindow(hWnd, nCmdShow);
/* Force the window to repaint itself */
UpdateWindow(hWnd);
/* Message loop */
while (1) {
/* execute idle function while no messages to process */
while (idleFunc &&
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
{
(*idleFunc)(hDC);
}
if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Next | Prev | Top | Contents | Index